package com.capinfo.commons.project.service.security.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;

import com.capinfo.commons.project.model.security.SystemResource;
import com.capinfo.commons.project.model.security.SystemRole;
import com.capinfo.commons.project.model.security.SystemUser;
import com.capinfo.commons.project.parameter.security.SystemRoleParameter;
import com.capinfo.commons.project.parameter.security.SystemUserParameter;
import com.capinfo.commons.project.service.security.SystemRoleService;
import com.capinfo.framework.dao.SearchCriteria.OrderRow;
import com.capinfo.framework.dao.SearchCriteriaBuilder;
import com.capinfo.framework.dao.impl.restriction.RestrictionExpression;
import com.capinfo.framework.model.BaseEntity;
import com.capinfo.framework.service.impl.CommonsDataOperationServiceImpl;
import com.capinfo.framework.util.StringUtils;

public class SystemRoleServiceImpl extends CommonsDataOperationServiceImpl<SystemRole,SystemRoleParameter> implements SystemRoleService {
	
	private static final Log logger = LogFactory.getLog(SystemRoleService.class);

	public List<SystemRole> getAllRoles() {
		
		return getGeneralService().getAllObjects(SystemRole.class);
	}

	public SearchCriteriaBuilder<SystemRole> getSearchCriteriaBuilder(SystemRoleParameter parameter) {
		
		SearchCriteriaBuilder<SystemRole> searchCriteriaBuilder = super.getSearchCriteriaBuilder(parameter);

		searchCriteriaBuilder.addQueryCondition("name", RestrictionExpression.LIKE_OP, parameter.getEntity().getName());
		searchCriteriaBuilder.addOrderCondition("id", OrderRow.ORDER_DESC);

		return searchCriteriaBuilder;
	}

	@Override
	public void populateParameter(SystemRoleParameter parameter) {
		
		super.populateParameter(parameter);
		
		SystemRole role = parameter.getEntity();
		
		Set<SystemResource> resources = role.getResources();
		
		parameter.setResourceIdString(formatArrayIdToString(resources));
		
	}
	
	public static String formatArrayIdToString(Set<? extends BaseEntity> entitys){
		
		String retString = "";

		for(Iterator<? extends BaseEntity> it = entitys.iterator(); it.hasNext() ; ){
			
			BaseEntity entity = it.next();
			retString += entity.getId();
			if(it.hasNext())
				retString +=",";
		}
		
		return retString;
	}
	
	@Override
	public SystemRole saveOrUpdate(SystemRoleParameter parameter) {

		return getCacheParameter(parameter).getNewEntity();
	}
	
	protected CacheParameter getCacheParameter(SystemRoleParameter parameter) {

		CacheParameter cacheParameter = new CacheParameter();
		SystemRole newEntity = null;
		if( parameter.getEntity().getId() == null ){
			
			newEntity = new SystemRole();
			//BeanUtils.copyProperties(parameter.getEntity(), newEntity, new String[]{"enabled","resources","users"});
		} else {
			
			newEntity = this.getObjectById(parameter);

			getGeneralService().fetchLazyProperty(newEntity, "resources");
			cacheParameter.setOriginalResources(newEntity.getResources());
		}
		if( null != newEntity ) {
			
			cacheParameter.setOriginalRoleName(newEntity.getName());
			BeanUtils.copyProperties(parameter.getEntity(), newEntity, new String[]{"enabled","resources","users","viewStamps"});
			
			newEntity.setResources(stringsToResources(parameter.getResourceIdString()));
			
			this.getGeneralService().saveOrUpdate(newEntity);
			cacheParameter.setNewEntity(newEntity);
		}
		
		return cacheParameter;
	}
	
	protected class CacheParameter {
		
		private SystemRole newEntity;
		private Set<SystemResource> originalResources = new HashSet<SystemResource>();
		private String originalRoleName;
		
		public CacheParameter() {}

		public SystemRole getNewEntity() {
			return newEntity;
		}

		public void setNewEntity(SystemRole newEntity) {
			this.newEntity = newEntity;
		}

		public Set<SystemResource> getOriginalResources() {
			return originalResources;
		}

		public void setOriginalResources(Set<SystemResource> originalResources) {
			this.originalResources = originalResources;
		}

		public String getOriginalRoleName() {
			return originalRoleName;
		}

		public void setOriginalRoleName(String originalRoleName) {
			this.originalRoleName = originalRoleName;
		}
	}

	private Set<SystemResource> stringsToResources(String ids){

		Set<SystemResource> resources = new HashSet<SystemResource>();
		if(org.apache.commons.lang.StringUtils.isNotBlank(ids) ) {

			if(ids.indexOf(",") == 0) {
				ids = ids.substring(1,ids.length());
			}
			if(ids.lastIndexOf(",")== ids.length()-1) {
				ids = ids.substring(0,ids.length()-1);
			}

			List<SystemResource> resourceList = new ArrayList<SystemResource>();
			if(ids.length()!= 0){
				SearchCriteriaBuilder<SystemResource> searchCriteriaBuilder = new SearchCriteriaBuilder<SystemResource>(SystemResource.class);
				searchCriteriaBuilder.addAdditionalRestrictionSql("ID in(" + ids + ")");
				resourceList = this.getGeneralService().getObjects(searchCriteriaBuilder.build());
			}
			for(SystemResource res : resourceList){
				resources.add(res);
			}
		}
		
		return resources;
	}
	
	public boolean validatorNameExists(SystemRoleParameter parameter) {
		SystemRole systemRole = parameter.getEntity();
		SearchCriteriaBuilder<SystemRole> searchCriteriaBuilder = new SearchCriteriaBuilder<SystemRole>(SystemRole.class);
		
		searchCriteriaBuilder.addQueryCondition("name", RestrictionExpression.EQUALS_OP, systemRole.getName());
		searchCriteriaBuilder.addQueryCondition("enabled", RestrictionExpression.EQUALS_OP, Boolean.TRUE);
		if (systemRole.getId() != null) {
			searchCriteriaBuilder.addQueryCondition("id", RestrictionExpression.NOT_EQUALS_OP, systemRole.getId());
		}
		return getGeneralService().getCount(searchCriteriaBuilder.build()) > 0 ? Boolean.TRUE : Boolean.FALSE;
	}
}
